// GLView.cpp
/* 
Copyright (c) 2009, Richard S. Wright Jr.
GLTools Open Source Library
All rights reserved.

Redistribution and use in source and binary forms, with or without modification, 
are permitted provided that the following conditions are met:

Redistributions of source code must retain the above copyright notice, this list 
of conditions and the following disclaimer.

Redistributions in binary form must reproduce the above copyright notice, this list 
of conditions and the following disclaimer in the documentation and/or other 
materials provided with the distribution.
bbud
Neither the name of Richard S. Wright Jr. nor the names of other contributors may be used 
to endorse or promote products derived from this software without specific prior 
written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 
SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 
TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

#include "GLView.h"


////////////////////////////////////////////////////////////////////////////
// Do not put any OpenGL code here. General guidence on constructors in 
// general is to not put anything that can fail here either (opening files,
// allocating memory, etc.)
GLView::GLView(void) : screenWidth(800), screenHeight(600), bFullScreen(false), bAnimated(true), samples(1), bGameMode(false)
	{
	buttonState = 0;
	joyState = 0;
	}
	
	
///////////////////////////////////////////////////////////////////////////////
// OpenGL related startup code is safe to put here. Load textures, etc.
void GLView::Initialize(void)
	{
	// Make sure OpenGL entry points are set
	glewInit();

	// Ugly plumb red picked on purpose... no a likely color to occur by accident.
	// So if you see this color, it means it's working ;-)
	glClearColor(0.8f, 0.4f, 0.4f, 1.0f);

	//Enable anything necessary
	glEnable(GL_DEPTH_TEST);
	glEnable(GL_CULL_FACE);

	//initialize variables
	shipSpeed = 8.0f;
	shipTurnSpeed = 50.0f;

	baseShader = gltLoadShaderPairWithAttributes("Resources/Shaders/Base.vp", "Resources/Shaders/Base.fp", 2, GLT_ATTRIBUTE_VERTEX, "vVertexPos",GLT_ATTRIBUTE_NORMAL, "VNormal");
	CheckShader(baseShader, "baseShader");

	uniBSMVP = glGetUniformLocation(baseShader, "mMVP");
	CheckUniform(uniBSMVP, "uniBSMVP");	

	uniBSMatColor = glGetUniformLocation(baseShader, "matColor");
	CheckUniform(uniBSMatColor, "uniBSMatColor");

	gltMakeSphere(sphereBatch, 1, 50, 25);

	orbitalAxis[0] = rand() % 2;
	orbitalAxis[1] = rand() % 2;
	orbitalAxis[2] = rand() % 2;

	}


///////////////////////////////////////////////////////////////////////////////
// Do your cleanup here. Free textures, display lists, buffer objects, etc.
void GLView::Shutdown(void)
	{


	}


///////////////////////////////////////////////////////////////////////////////
// This is called at least once and before any rendering occurs. If the screen
// is a resizeable window, then this will also get called whenever the window
// is resized.
void GLView::Resize(GLsizei nWidth, GLsizei nHeight)
	{
	glViewport(0, 0, nWidth, nHeight);

	// This is a good place to recompute your projection matrix.
	m3dMakePerspectiveMatrix(projMatrix, m3dDegToRad(60.0f), float(nWidth)/float(nHeight), 1.0f, 100.0f);
	}


///////////////////////////////////////////////////////////////////////////////
// Render a frame. The owning framework is responsible for buffer swaps,
// flushes, etc.
void GLView::Render(void)
{
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

	MoveCamera();

	glCullFace(GL_BACK);

	modelViewMatrix.PushMatrix();
	{
		M3DMatrix44f mCamera;
		camera.GetCameraMatrix(mCamera);
		modelViewMatrix.MultMatrix(mCamera);

		//Draw Saturn
		modelViewMatrix.PushMatrix();
		{
			glUseProgram(baseShader);

			modelViewMatrix.Translate(0.0f, 0.0f, -15.0f);
			//modelViewMatrix.Rotate(rotWatch.GetElapsedSeconds() * 30, 0.0f, 1.0f, 0.0f);

			modelViewMatrix.Scale(2.0f, 2.0f, 2.0f);

			M3DMatrix44f mMVP;
			m3dMatrixMultiply44(mMVP, projMatrix, modelViewMatrix.GetMatrix());
			glUniformMatrix4fv(uniBSMVP, 1, GL_FALSE, mMVP);

			M3DVector4f matColor = { 0.0f, 1.0f, 0.0f, 1.0f };
			glUniform4fv(uniBSMatColor, 1, matColor);

			sphereBatch.Draw();


			//DrawMoons
			modelViewMatrix.PushMatrix();
			{
				M3DVector3f position = {
					cos(m3dDegToRad(rotWatch.GetElapsedSeconds() * 60)) * 5,
					0.0f							 ,
					sin(m3dDegToRad(rotWatch.GetElapsedSeconds() * 60)) * 5
				};
				moonOrbitTest.SetOrigin(position);

				M3DMatrix44f rotationMatrix;
				m3dRotationMatrix44(rotationMatrix, 45, orbitalAxis[0], orbitalAxis[1], orbitalAxis[2]);
				

				modelViewMatrix.MultMatrix(rotationMatrix);
				modelViewMatrix.MultMatrix(moonOrbitTest);

				M3DMatrix44f mvMatrix;
				modelViewMatrix.GetMatrix(mvMatrix);
				////moonOrbitTest.SetOrigin(mvMatrix[12], mvMatrix[13], mvMatrix[14]);

				modelViewMatrix.Scale(.5f,.5f,.5f);

				m3dMatrixMultiply44(mMVP, projMatrix, modelViewMatrix.GetMatrix());
				glUniformMatrix4fv(uniBSMVP, 1, GL_FALSE, mMVP);

				M3DVector4f matColor = { 1.0f, 0.0f, 0.0f, 1.0f };
				glUniform4fv(uniBSMatColor, 1, matColor);

				sphereBatch.Draw();


			}
			modelViewMatrix.PopMatrix();
		}
		modelViewMatrix.PopMatrix();

	}
	modelViewMatrix.PopMatrix();



	}

void GLView::MoveCamera(){
	float timePassed = stopwatch.GetElapsedSeconds();

	if (GetAsyncKeyState('W'))
		camera.MoveForward(shipSpeed * timePassed);

	if (GetAsyncKeyState('S'))
		camera.MoveForward(-shipSpeed * timePassed);

	if (GetAsyncKeyState('A'))
		camera.MoveRight(shipSpeed * timePassed);

	if (GetAsyncKeyState('D'))
		camera.MoveRight(-shipSpeed * timePassed);

	if (GetAsyncKeyState('Q'))
		camera.RotateWorld(m3dDegToRad(shipTurnSpeed) * timePassed, 0.0f, 1.0f, 0.0f);

	if (GetAsyncKeyState('E'))
		camera.RotateWorld(m3dDegToRad(-shipTurnSpeed) * timePassed, 0.0f, 1.0f, 0.0f);

	if (GetAsyncKeyState('R'))
		camera.RotateLocalX(m3dDegToRad(-shipTurnSpeed)* timePassed);

	if (GetAsyncKeyState('C'))
		camera.RotateLocalX(m3dDegToRad(shipTurnSpeed)* timePassed);

	if (GetAsyncKeyState(VK_SHIFT))
		camera.MoveUp(-shipSpeed * timePassed);

	if (GetAsyncKeyState(VK_SPACE))
		camera.MoveUp(shipSpeed * timePassed);

	stopwatch.Reset();

}
